package com.mframe.persist;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.mframe.query.PageData;
import com.mframe.system.MFrameConstant;

@SuppressWarnings("unchecked")
public abstract class PublicDAOImpl extends HibernateDaoSupport implements
		PublicDAO {
	
	public <T> void delete(T entity) {
		getHibernateTemplate().delete(entity);
		getHibernateTemplate().flush();
	}

	public <T> void deleteById(Serializable id, Class<T> clazz) {
		T entity = getHibernateTemplate().get(clazz, id);
		getHibernateTemplate().delete(entity);
	}

	
	public int executeHql(final String hql, final Object[] args) {
		Integer ret = getHibernateTemplate().execute(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				if (args != null) {
					for (int i = 0; i < args.length; i++) {
						query.setParameter(i, args[i]);
					}
				}
				int r = query.executeUpdate();
				return new Integer(r);
			}

		});
		return ret == null ? 0 : ret.intValue();
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String hql, Object[] args) {
		List<T> list = null;
		list = (List<T>) getHibernateTemplate().find(hql, args);
		return list == null ? new ArrayList<T>(0) : list;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String hql, Map<String, Object> args) {
		if (args.isEmpty() || args == null) {
			return findByHql(hql, new Object[] {});
		}
		String[] paramNames = new String[args.size()];
		Object[] paramValues = new Object[args.size()];
		int i = 0;
		/**
		 * 将之前使用字串获取改成这种方式更加方便
		 */
		for (Entry<String, Object> param : args.entrySet()) {
			paramNames[i] = param.getKey();
			paramValues[i] = param.getValue();
			i++;
		}
		List<T> list = (List<T>) getHibernateTemplate().findByNamedParam(hql,
				paramNames, paramValues);
		return list == null ? new ArrayList<T>(0) : list;
	}

	public boolean findExists(String hql, Object[] args) {
		Integer iCount = (Integer)findByHql(hql, args).size();
		return iCount >0 ? true : false;
	}
	
	@SuppressWarnings("unchecked")
	public PageData findForPage(final String hql,final Map<String, Object> pmap,
			final int topage,final int pagesize) {		
		return ((PageData)getHibernateTemplate().execute(new HibernateCallback() {
			public PageData doInHibernate(Session session)
					throws HibernateException, SQLException {
				//1.获取总行数（totalRow）
				//如果有select则把from之前的改成 count(*)
				PageData pageData=new PageData();
				pageData.setCurrentPage(topage);
				String hstr=hql;
				int beginPos=hql.trim().toUpperCase().indexOf("FROM ");
				int endPos=hql.trim().toUpperCase().indexOf("ORDER ");
				if(beginPos<=0){
					hstr="select count(*) "+hstr.substring(beginPos);
				}else{
					hstr="select count(*) "+hstr.substring(beginPos,endPos);
				}
				Query query = session.createQuery(hstr);
				if(pmap!=null){
					addQueryParam(query,pmap);
				}
				Integer totalRows= Integer.valueOf(query.list().get(0).toString());
				pageData.setTotalRows(totalRows);
				
				//2执行查询
				query=session.createQuery(hql);
				if(pmap!=null){
					addQueryParam(query,pmap);
				}				
				
				//3 开始分页(PageData赋值)
				int size=pagesize;
				if(size<=0)
					size=MFrameConstant.M_PAGE_SIZE;
				//设置到pageData里去
				pageData.setPagesize(size);
				//从0开始
				int fromrow=(topage-1)*size;
				query.setFirstResult(fromrow);
				query.setMaxResults(size);
				//分页开始
				List data=query.list();
				pageData.setDatals(data);
				
				//行号
				pageData.setFromRowId(fromrow + 1);
				pageData.setToRowId(fromrow+data.size());
				int pagenum =(totalRows%size ==0)?totalRows/size :totalRows/size+1;
				pageData.setTotalPageNum(pagenum);
				return null;
			}
		}));
	}
	
	/**
	 * 将所有的条件插入到query中
	 * @param query
	 * @param param
	 * @return
	 */
	private static Query addQueryParam(Query query,Map<String,Object> param){
		Set<String> keys = param.keySet();
		for (String str : keys) {
			query.setParameter(str, param.get(str));
		}
		return query;
	}
	
	public int findRecordCount(String hql, Object[] args) {
		Integer iCount = (Integer)findByHql(hql, args).size();		
		return iCount.intValue();
	}

	public <T> T getById(Class<T> clazz, Serializable id) {
		return getHibernateTemplate().get(clazz, id);
	}

	public <T> T loadById(Class<T> clazz, Serializable id) {
		return getHibernateTemplate().load(clazz, id);
	}

	public Object merge(Object entity) {
		return getHibernateTemplate().merge(entity);
	}

	public <T> void save(T entity) {
		getHibernateTemplate().save(entity);
	}

	public <T> T saveOrUpdate(T entity) {
		getHibernateTemplate().saveOrUpdate(entity);
		return entity;
	}

	public <T> void update(T entity) {
		getHibernateTemplate().update(entity);
	}
}
